
#include "stdafx.h"
#ifndef _NOSERVER_

#include "Inject.h"
#include "InjectDelegate.h"
#include "Utility.h"
#include "CFWeb.h"
#include "JSONMsg.h"

LPCSTR skipStr(LPCSTR v)
{
	if (!v) return nullptr;
	for (; *v; v++);
	v++; return *v ? v : nullptr;
}

void Pause(LPCVOID data, intptr_t id)
{
	printf_s("pause");
}
LPCVOID WebGet(LPCSTR sUrl, intptr_t *pDataLength, byte *bodyData, intptr_t bodyDataLength, const propertyStruct *propertys, intptr_t propCount)
{
	CCFWeb cfWeb; return cfWeb.WebGet(sUrl, pDataLength, bodyData, bodyDataLength, propertys, propCount);
}
LPCVOID WebPost(LPCSTR sUrl, intptr_t *pDataLength, byte *bodyData, intptr_t bodyDataLength, const propertyStruct *propertys, intptr_t propCount)
{
	CCFWeb cfWeb; return cfWeb.WebPost(sUrl, pDataLength, bodyData, bodyDataLength, propertys, propCount);
}
bool SvScreenJpg(HWND hwnd, IStream * pStream, int quality, CRect *pRect)
{
	return SaveScreenJpg(hwnd, pStream, quality, pRect);
}
static CInjectDelegate *pInject = nullptr;
void SendInjectMessage(CJSONMsg &msg)
{
	if (pInject) pInject->SendLargeMessage(msg);
}
void MsgInit(CJSONMsg &msg, char maincmd, char subcmd)
{
	msg.init(maincmd, subcmd);
}
void MsgAddSTRField(CJSONMsg &msg, LPCSTR fieldName, LPCSTR value)
{
	msg.AddField(fieldName, value);
}
void MsgAddIntField(CJSONMsg &msg, LPCSTR fieldName, int value)
{
	msg.AddField(fieldName, value);
}
void MsgAddData(CJSONMsg &msg, LPVOID data, intptr_t dataLength, bool copyData)
{
	msg.AddData(data, dataLength, copyData);
}

bool MakeInject(LPCWSTR extra)
{
	pInject = new CInjectDelegate(); if (pInject) pInject->Start(0); else return false;
	bool bRet = false;
	do {
		intptr_t szData; LPCVOID pData = pInject->GetInjectData(szData); if (!pData || szData <= 0) break;
		intptr_t szFunc, offset; LPCVOID pFunc = pInject->GetInjectFunc(szFunc, offset); if (!pFunc || szFunc <= 0 || offset >= szFunc) break;
		LPVOID useData = HeapAlloc(GetProcessHeap(), 0, szData);
		if (useData)
		do {
			memcpy_s(useData, szData, pData, szData);
			DWORD op; VirtualProtect((LPVOID)pFunc, szFunc, PAGE_EXECUTE_READWRITE, &op);
			bool faild = false; int entryCount = *((int*)useData); LPCVOID *entry = (LPCVOID*)((size_t)useData + sizeof(int));
			LPCSTR entryName = (LPCSTR)((size_t)useData + *((int*)((size_t)useData + sizeof(int) + entryCount*sizeof(LPCVOID))));
			HMODULE hDll = nullptr;
			for (intptr_t i = 0; !faild && i < entryCount; i++)
			{
				switch (i)
				{
				case Func_Pause:			entry[i] = &Pause; break;
				case Func_WebGet:			entry[i] = &WebGet; break;
				case Func_WebPost:			entry[i] = &WebPost; break;
				case Func_SaveScreenJpg:	entry[i] = &SvScreenJpg; break;
				case Func_SendRemoteMessage:entry[i] = &SendInjectMessage; break;
				case Func_MsgInit:			entry[i] = &MsgInit; break;
				case Func_MsgAddSTRField:	entry[i] = &MsgAddSTRField; break;
				case Func_MsgAddIntField:	entry[i] = &MsgAddIntField; break;
				case Func_MsgAddData:		entry[i] = &MsgAddData; break;
				case Func_GetShellPath:		entry[i] = &GetShellPath; break;
				default:
					while (entryName && strstr(entryName, ".DLL"))
					{
						if (hDll) FreeLibrary(hDll);
						hDll = LoadLibraryA(entryName); entryName = skipStr(entryName);
					}
					if (!entryName || !hDll)
						faild = true;
					else
					{
						entry[i] = GetProcAddress(hDll, entryName); entryName = skipStr(entryName);
						if (entry[i] == 0) faild = true;
					}
					break;
				}
			}
			if (hDll) FreeLibrary(hDll);
			if (!faild)
			{
				fnInjMain InjMain = (fnInjMain)((size_t)pFunc + offset);
				if (pInject) for (TICK tk = TICK::Now(1000); !pInject->IsConnected() && TICK::Now() < tk; IDLE());
				CJSONMsg msg; InjMain(useData, msg); bRet = true;
				if (extra)
				{
					msg.init(MainCmd_JSONData, SubCmd_Log); msg.AddField("msg", extra); SendInjectMessage(msg);
				}
			}
			VirtualProtect((LPVOID)pFunc, szFunc, op, &op);
		} while (0);
		if (useData) HeapFree(GetProcessHeap(), 0, useData);
	} while (0);
	pInject->Stop(true); delete pInject; pInject = nullptr;
	return bRet;
}

#endif
